package org.study.mybatisplus.dynamic.boot.service.impl;

import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import org.study.mybatisplus.dynamic.boot.config.SystemConstant;
import org.study.mybatisplus.dynamic.boot.dto.CreateDeviceDTO;
import org.study.mybatisplus.dynamic.boot.mapper.*;
import org.study.mybatisplus.dynamic.boot.model.IotDevice;
import org.study.mybatisplus.dynamic.boot.model.IotDeviceProperty;
import org.study.mybatisplus.dynamic.boot.service.DmlService;
import org.study.mybatisplus.dynamic.boot.util.TDengineUtils.DateTypeEnum;

import java.util.List;

/**
 * 作用描述
 *
 * @author doveylovey
 * @version v1.0.0
 * @email 1135782208@qq.com
 * @date 2024年11月27日
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class DmlServiceImpl implements DmlService {
    private final IotDeviceMapper iotDeviceMapper;
    private final IotDevicePropertyMapper iotDevicePropertyMapper;
    private final IotDatasourceMapper iotDatasourceMapper;

    @Override
    public Boolean addDeviceProperty2Table(Long queryProjectId, Long queryDeviceId) {
        List<IotDevice> deviceList = iotDeviceMapper.selectList(Wrappers.lambdaQuery(IotDevice.class)
                .eq(IotDevice::getProjectId, queryProjectId)
                .eq(queryDeviceId != null, IotDevice::getId, queryDeviceId)
                .eq(IotDevice::getIsDeleted, SystemConstant.DB_NOT_DELETED)
        );
        if (CollectionUtils.isEmpty(deviceList)) {
            log.info("暂无设备");
            return Boolean.TRUE;
        }
        deviceList.forEach(iotDevice -> {
            Long deviceId = iotDevice.getId();
            Long projectId = iotDevice.getProjectId();
            String gatewayNo = iotDevice.getGatewayNo();
            String deviceNo = iotDevice.getDeviceNo();
            List<IotDeviceProperty> devicePropertyList = iotDevicePropertyMapper.selectList(Wrappers.lambdaQuery(IotDeviceProperty.class)
                    .eq(IotDeviceProperty::getProjectId, queryProjectId)
                    .eq(IotDeviceProperty::getDeviceId, deviceId)
                    .eq(IotDeviceProperty::getIsDeleted, SystemConstant.DB_NOT_DELETED)
            );
            if (CollectionUtils.isNotEmpty(devicePropertyList)) {
                try {
                    DynamicDataSourceContextHolder.push(SystemConstant.DS_TDENGINE);
                    List<CreateDeviceDTO> insertList = Lists.newArrayList();
                    devicePropertyList.forEach(iotDeviceProperty -> {
                        CreateDeviceDTO createDeviceDTO = CreateDeviceDTO.builder()
                                .propertyNo(iotDeviceProperty.getPropertyNo())
                                .propertyType(iotDeviceProperty.getPropertyType())
                                .build();
                        if (DateTypeEnum.BINARY.getDateType().equalsIgnoreCase(iotDeviceProperty.getPropertyType()) ||
                                DateTypeEnum.VARCHAR.getDateType().equalsIgnoreCase(iotDeviceProperty.getPropertyType()) ||
                                DateTypeEnum.VARBINARY.getDateType().equalsIgnoreCase(iotDeviceProperty.getPropertyType()) ||
                                DateTypeEnum.NCHAR.getDateType().equalsIgnoreCase(iotDeviceProperty.getPropertyType())) {
                            createDeviceDTO.setPropertyScale(iotDeviceProperty.getPropertyScale() == null ? "32" : String.valueOf(iotDeviceProperty.getPropertyScale()));
                        } else if (DateTypeEnum.DECIMAL.getDateType().equalsIgnoreCase(iotDeviceProperty.getPropertyType())) {
                            createDeviceDTO.setPropertyScale("18, 6");
                        } else {
                            createDeviceDTO.setPropertyScale(null);
                        }
                        insertList.add(createDeviceDTO);
                    });
                    // 创建数据表
                    String tableName = "property_" + projectId + "_" + deviceId;
                    iotDatasourceMapper.createTableWithFiled(tableName, gatewayNo, deviceNo, insertList);
                    // 创建日志表
                    iotDatasourceMapper.createLogTable("log_" + projectId + "_" + deviceId, "设备日志_" + deviceId);
                } catch (Exception ex) {
                    log.error("操作数据源【" + SystemConstant.DS_TDENGINE + "】失败", ex);
                    throw new RuntimeException("操作数据源【" + SystemConstant.DS_TDENGINE + "】失败");
                } finally {
                    DynamicDataSourceContextHolder.clear();
                }
            }
        });
        return Boolean.TRUE;
    }

    @Override
    public Boolean addDeviceProperty2Table(String queryGatewayNo, String queryDeviceNo) {
        List<IotDevice> deviceList = iotDeviceMapper.selectList(Wrappers.lambdaQuery(IotDevice.class)
                .eq(IotDevice::getGatewayNo, queryGatewayNo)
                .eq(IotDevice::getDeviceNo, queryDeviceNo)
                .eq(IotDevice::getIsDeleted, SystemConstant.DB_NOT_DELETED)
        );
        if (CollectionUtils.isEmpty(deviceList)) {
            log.info("暂无设备");
            return Boolean.TRUE;
        }
        deviceList.forEach(iotDevice -> {
            Long deviceId = iotDevice.getId();
            Long projectId = iotDevice.getProjectId();
            String gatewayNo = iotDevice.getGatewayNo();
            String deviceNo = iotDevice.getDeviceNo();
            List<IotDeviceProperty> devicePropertyList = iotDevicePropertyMapper.selectList(Wrappers.lambdaQuery(IotDeviceProperty.class)
                    .eq(IotDeviceProperty::getProjectId, iotDevice.getProjectId())
                    .eq(IotDeviceProperty::getDeviceId, deviceId)
                    .eq(IotDeviceProperty::getIsDeleted, SystemConstant.DB_NOT_DELETED)
            );
            if (CollectionUtils.isNotEmpty(devicePropertyList)) {
                try {
                    DynamicDataSourceContextHolder.push(SystemConstant.DS_TDENGINE);
                    List<CreateDeviceDTO> insertList = Lists.newArrayList();
                    devicePropertyList.forEach(iotDeviceProperty -> {
                        CreateDeviceDTO createDeviceDTO = CreateDeviceDTO.builder()
                                .propertyNo(iotDeviceProperty.getPropertyNo())
                                .propertyType(iotDeviceProperty.getPropertyType())
                                .build();
                        if (DateTypeEnum.BINARY.getDateType().equalsIgnoreCase(iotDeviceProperty.getPropertyType()) ||
                                DateTypeEnum.VARCHAR.getDateType().equalsIgnoreCase(iotDeviceProperty.getPropertyType()) ||
                                DateTypeEnum.VARBINARY.getDateType().equalsIgnoreCase(iotDeviceProperty.getPropertyType()) ||
                                DateTypeEnum.NCHAR.getDateType().equalsIgnoreCase(iotDeviceProperty.getPropertyType())) {
                            createDeviceDTO.setPropertyScale(iotDeviceProperty.getPropertyScale() == null ? "32" : String.valueOf(iotDeviceProperty.getPropertyScale()));
                        } else if (DateTypeEnum.DECIMAL.getDateType().equalsIgnoreCase(iotDeviceProperty.getPropertyType())) {
                            createDeviceDTO.setPropertyScale("18, 6");
                        } else {
                            createDeviceDTO.setPropertyScale(null);
                        }
                        insertList.add(createDeviceDTO);
                    });
                    // 创建数据表
                    String tableName = "property_" + projectId + "_" + deviceId;
                    iotDatasourceMapper.createTableWithFiled(tableName, gatewayNo, deviceNo, insertList);
                    // 创建日志表
                    iotDatasourceMapper.createLogTable("log_" + projectId + "_" + deviceId, "设备日志_" + deviceId);
                } catch (Exception ex) {
                    log.error("操作数据源【" + SystemConstant.DS_TDENGINE + "】失败", ex);
                    throw new RuntimeException("操作数据源【" + SystemConstant.DS_TDENGINE + "】失败");
                } finally {
                    DynamicDataSourceContextHolder.clear();
                }
            }
        });
        return Boolean.TRUE;
    }
}
